/**
  SUNNY Project, Anyang Normal University, IMP-CAS
	\class TASPStateManager
	\brief A list of TASPState objects, responsible for reading the
	 user-input single-particle (SP) state files, generating SP state objects,
	and managing the SP states. Note that this is a singleton class.
	\author SUN Yazhou
	\since 2020/01/31
	\date Last modified: 2022/11/15 by SUN Yazhou
	\copyright 2020-2023 SUN Yazhou
	\copyright SUNNY project, Anyang Normal University, IMP-CAS
*/

#include <string>
#include <cstring>
#include <unistd.h>
#include <iostream>
#include <iomanip>
#include "TASPState.h"
#include "TASPStateManager.h"
#include "TAException.h"
#include "TAYaml.h"

using std::string;
using std::cout;
using std::endl;
using std::setw;

TASPStateManager *TASPStateManager::kInstance = nullptr;

TASPStateManager::TASPStateManager(){}

TASPStateManager *TASPStateManager::Instance(){
	if(!kInstance) kInstance = new TASPStateManager();
	return kInstance;
}

TASPStateManager::~TASPStateManager(){
	for(TASPState *&p : fSPStateVec){
		if(p){ delete p; p = nullptr; }
	} // end for
	fSPStateVec.clear();
} // end the destructor

int TASPStateManager::GetNSPState() const{
	if(!fSPStateVec.size()){
		TAException::Warn("TASPStateManager",
			"GetNSPState: The fSPStateVec is empty.");
	}
	return fSPStateVec.size();
} // end member function GetNSPState

// return fSPStateVec[i]
TASPState *TASPStateManager::operator[](int i){
	if(i < 0 || i >= int(fSPStateVec.size())) TAException::Error("TASPStateManager",
		"operator[]: input subscript i=%d out of range", i);
	return fSPStateVec[i];
} // end member function operator[]


void TASPStateManager::LoadSPListFile(const string &file){
	if(access(file.c_str(), F_OK)) TAException::Error("TASPStateManager",
		 "LoadSPListFile: file %s non-existent", file.c_str());
	TAYaml pa(file);
	int i = -1; //
	const YAML::Node &sp = pa["sps"];
	int n, l, two_j, two_mj, two_tz; double energy;
	while(sp[++i]){
		const YAML::Node &m = sp[i];
		n = m[0].as<int>();
		l = m[1].as<int>();
		two_j = m[2].as<int>();
		two_mj = m[3].as<int>();
		two_tz = m[4].as<int>();
		energy = m[5].as<double>();
		fSPStateVec.push_back(new TASPState(i, n, l, two_j, two_mj, two_tz, energy));
	} // end while
} // end member function LoadSPListFile()

void TASPStateManager::Print() const{
	const int n = fSPStateVec.size();
	if(n <= 0) return;
	cout << "\033[33;1mTotally " << n << " single-particle states read in\033[0m";
	cout << endl;
	cout << "index" << setw(3) << "n" << setw(3) << "l" << setw(4) << "2j";
	cout << setw(5) << "2mj" << setw(5) << "2tz" << setw(6) << "e_sp" << endl;
	for(TASPState *sp : fSPStateVec) sp->Print(); // DEBUG
	cout << endl;
	// getchar(); // DEBUG
} // end member function ShowSPState
